; MATHLIB: a 16 Bit Arithmetic Package for Z80
; Sourced 26 Nov '80 by Trevor Marshall
;			SYSOP, Thousand Oaks Tech RBBS
;
;
MULTIPLY: ; 16 x 16 Bit multiplication
; (may be truncated to 16 x n bits)
;
;result (HL) = multiplicand (DE) x multiplier (BC)
;
; The multiplicand is in DE
; The multiplier is in BC
; The result will be in HL
; It overflows safely, but without indication
; Registers are destroyed
;
;	Example: 5 x 3
;		101
;	     x  011
;	----------------
;		101	(Shifted LSBit=1)
;	       101	(Shifted LSBit=1)
;	      000	(Shifted LSBit=0,no add)
;	----------------
;	      01111	(Result)
;
;  Multiplier is in BC
	LD	A,16	; Loop count in A
;This count must be >= the number of bits used in BC
;
	LD	HL,0	;Clear result
;
ZZMULT:	
; is multiplier LSBit = 1 ?
	SRL	B	;Right shift multiplier MSB
			; 0 -> MSBit, LSBit -> Carry
	RR	C	;Rotate right multiplier LSB
			;Carry -> MSBit, LSBit -> Carry
	JR	NC,ZZNOADD ;LSBit not 1, Dont add
;
; Could test for overflow by using this here:
;	CCF	;Carry will be 1, C -> 0
;	ADC	HL,DE
;	JR	C,OVERFLOW.ROUTINE
; But will use the simpler
	ADD	HL,DE	;LSBit = 1, so add multiplicand
			;	to (shifted) result
;
ZZNOADD:
;Now we shift left the multiplicand
	SLA	E	; 0 -> LSBit, MSBit -> Carry
	RL	D	; Carry -> LSBit, MSBit -> Carry
;
	DEC	A	;Loop cntr
	JR	NZ,ZZMULT
;
	RET	; ***** DONE *****
;
;-------------------------------------------------------
;
DIVIDE:		;16 Bit by 16 Bit Integer Division
;
;			dividend (BC)
;	result (BC) = --------------- + remainder (HL)
;			divisor  (DE)
;
; The dividend is in BC, and the result returns in BC
; The divisor is in DE
; After the division HL contains the remainder
;
; The divisor is successively subtracted from the high 
;   order bits of the dividend. After each subtraction 
;   the result is used instead of the initial dividend
; The result is increased by 1 each time.
; When the result of the subtraction is negative the 
;   partial result is restored by adding the divisor 
;   back to it.
; The result is simulataneously decremented by 1
;
;First check if divisor is 0
	LD	A,D
	OR	E
	JR	Z,DIVIDE.BY.ZERO
; Dividend is in BC
;clear result
	LD	HL,0
;loop counter
	LD	A,16	;DO NOT TRUNCATE
;
;Rotate Dividend left 
;Carry has been zeroed by the OR E above
ZZDIV1:	RL	C	;Carry -> LSBit, MSBit -> Carry
	RL	B		;ditto
;Rotate Remainder left
	ADC	HL,HL	;Never sets carry,
			;  ie RESETS carry
;Trial subtraction of divisor from result
	SBC	HL,DE	;Carry -> 0 if no borrow
			;Carry -> 1 if borrow
	JR	NC,ZZPOS
;otherwise negative
	ADD	HL,DE	;Restore dividend
ZZPOS:	CCF	;Calc Result Bit, Z80 carry peculiar
	DEC	A	;Loop counter
	JR	NZ,ZZDIV1	;Loop for 16 Bits
;
	RL	C	;Shift in last result bit
	RL	B
; The result is in BC, the remainder in HL
;
	RET	; ***** DONE ****
;
DIVIDE.BY.ZERO: LD  BC,0FFFFH ;Infinity
; Output a diagnostic message if desired
	RET
;
